﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using SoftwareConsulting.BI11.Studio.InternalServices;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.UI.Properties;
using SoftwareConsulting.BI11.NumericalMethods;

namespace SoftwareConsulting.BI11.Studio.UI.ProjectExplorer.ClassificationProblems
{
    public partial class SetClassificationProblemAttributesGroupsAndDifferenceDialog : RestorableForm
    {
        private IClassificationProblemWithTraining _problem; //задача классификации с обучением        

        /// <summary>
        /// Инициализирует диалог
        /// </summary>
        private void Initialize()
        {
            DMinimumGroupMatchingBox.Value = _problem.DMinimumGroupMatching;
            var rows = InfosGrid.Rows;
            rows.Clear();
            var attributes = _problem.AttributesNames;
            if (attributes == null)
            {
                OKButton.Enabled = false;
                return;
            }
            for (int i = 1; i < attributes.GetIndicatorValuesCount(); i++)//с первого, т.к. 0й - [не важно]
            {
                int attributeIndex = i - 1;
                rows.Add();
                var row = rows[attributeIndex];
                var cells = row.Cells;
                string attributeName = attributes.GetIndicatorValueByPosition(i).Value as string;
                (cells[0] as DataGridViewTextBoxCell).Value = attributeName;
                (cells[1] as DataGridViewTextBoxCell).Value = _problem.GetAttributeInfo(attributeIndex).ToString(CultureInfo.CurrentUICulture);
                int group = _problem.GetAttributeGroup(attributeIndex);
                //в интерфейсе поддерживаются не все группы
                bool correctgroup = ClassificationProblemGroupsProcessor.IsCorrectGroup(group);
                if (!correctgroup)
                {
                    GeneralMethods.ShowWarning(string.Format(Resources.BI_PROJECTEXPLORER_CLASSIFICATIONPROBLEM_WITHTRAINING_SETATTRIBUTESINFO_GROUPSANDDIFFERENCE_INCORRECTGROUP, attributeName, group.ToString(CultureInfo.CurrentUICulture)));                    
                }
                group = ClassificationProblemGroupsProcessor.CorrectGroup(group);
                var groupCell = cells[2] as DataGridViewImageCell;
                groupCell.Value = ClassificationProblemGroupsProcessor.Pictures[group];
                groupCell.Tag = group;
            }
        }

        /// <summary>
        /// Обрабатывает клик по ячейке грида
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="colIndex"></param>
        private void ProcessCellContentClick(int rowIndex, int colIndex)
        {
            if ((rowIndex >= 0) && (colIndex == 2))
            {
                //цвет группы меняем
                var rows = InfosGrid.Rows;
                var row = rows[rowIndex];
                var groupCell = row.Cells[colIndex] as DataGridViewImageCell;
                int group = ((int)groupCell.Tag) + 1;
                group = ClassificationProblemGroupsProcessor.CorrectGroup(group, true);
                groupCell.Value = ClassificationProblemGroupsProcessor.Pictures[group];
                groupCell.Tag = group;
            }
        }

        /// <summary>
        /// Применяет изменения и закрывает диалог
        /// </summary>
        private void ApplyAndClose()
        {            
            var rows = InfosGrid.Rows;
            var attributes = _problem.AttributesNames;
            double[] differences = new double[rows.Count];
            for (int i = 0; i < rows.Count; i++)
            {
                var row = rows[i];
                var cells = row.Cells;
                string valStr = (cells[1] as DataGridViewTextBoxCell).Value as string;
                double val = 0;
                bool parsed = double.TryParse(valStr, NumberStyles.Float, CultureInfo.CurrentUICulture, out val);
                parsed = parsed && (val >= 0);
                if (!parsed)
                {
                    GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_CLASSIFICATIONPROBLEM_WITHTRAINING_SETATTRIBUTESINFO_GROUPSANDDIFFERENCE_INCORRECTDIFFERENCE);
                    cells[1].Selected = true;
                    InfosGrid.CurrentCell = cells[1];
                    InfosGrid.BeginEdit(true);
                    DialogResult = DialogResult.None;
                    return;
                }
                differences[i] = val;
            }
            int[] groupsBefore = new int[rows.Count];
            ///нельзя задавать сразу в первом цикле, 
            ///т.к. если были ошибки ввода, то предыдущие 
            ///правильно введенные строки не должны применяться            
            for (int i = 0; i < rows.Count; i++)
            {
                groupsBefore[i] = _problem.GetAttributeGroup(i);
                _problem.SetAttributeGroup(i, (int)rows[i].Cells[2].Tag);
            }
            try
            {                                                
                _problem.SetDMinimumGroupMatching(Convert.ToInt32(DMinimumGroupMatchingBox.Value));                
            }                        
            catch (BIClassificationAttributesGroupTooShortException ex)
            {
                GeneralMethods.ShowUserError(ex.Message);
                for (int i = 0; i < rows.Count; i++)
                {                    
                    _problem.SetAttributeGroup(i, groupsBefore[i]);
                }
                DialogResult = DialogResult.None;
                return;
            }
            for (int i = 0; i < rows.Count; i++)
            {
                _problem.SetAttributeInfo(i, differences[i]);
            }            
            DialogResult = DialogResult.OK;
            Close();
        }

        /// <summary>
        /// Отменяет изменения и закрывает диалог
        /// </summary>
        private void CancelAndClose()
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        public SetClassificationProblemAttributesGroupsAndDifferenceDialog(IClassificationProblemWithTraining problem)
        {
            _problem = problem;
            InitializeComponent();
        }

        private void OKButton_Click(object sender, EventArgs e)
        {
            ApplyAndClose();
        }

        private void CancelInfosButton_Click(object sender, EventArgs e)
        {
            CancelAndClose();
        }

        private void SetClassificationProblemAttributesGroupsAndDifferenceDialog_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        private void InfosGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            ProcessCellContentClick(e.RowIndex, e.ColumnIndex);
        }
    }
}
